﻿using System.Text.Json.Serialization;

namespace Devonline.AspNetCore
{
    /// <summary>
    /// 嵌套的查询过滤选项, 代表字段内的字段和值的关系
    /// 典型样式为: 
    /// Name eq '张三'
    /// Age gt 20
    /// Name co '张三'
    /// not support: contains(Name, '张三')
    /// not support: contains(tolower(Name), 'lucy')
    /// not support: Name not eq '张三'
    /// not support: Name eq '张三' and Age ge 20
    /// not support: Age ge 20 and (Name co '张' or Name co '李')
    /// not support: Age ge 20 and (Name co '张' or Name co '李' and Gender eq 'Male')
    /// not support: Age ge 20 and (Name co '张' or Name co '李') or Gender eq 'Male'
    /// not support: Age ge 20 and (Name co '张' or Name co '李' and Gender eq 'Male') or UserType eq 'Administrator'
    /// </summary>
    public class NestedFilterOption : FilterOption
    {
        /// <summary>
        /// logic expression list
        /// </summary>
        internal static readonly string[] LogicExpression = new string[] { " and ", " or " };

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public NestedFilterOption(Type type) : base(type) { }
        /// <summary>
        /// 字符串 filter 表示形式参数的构造函数
        /// </summary>
        /// <param name="filter"></param>
        public NestedFilterOption(Type type, string filter) : base(type, filter)
        {
            //目前仅支持一级嵌套, 且不支持小括号表达式
            var values = filter.Split(LogicExpression, StringSplitOptions.RemoveEmptyEntries);
            if (values.IsNullOrEmpty())
            {
                throw new ArgumentException($"filter {filter} expression error!");
            }

            var filters = new List<FilterOption>();
            foreach (var value in values)
            {
                filters.Add(new FilterOption(type, value));
            }

            Filters = filters;
        }

        /// <summary>
        /// 内部字段之间的逻辑, and, or等
        /// </summary>
        [JsonPropertyName("logic")]
        public LogicType? Logic { get; set; }
        /// <summary>
        /// 内部字段选项
        /// </summary>
        [JsonPropertyName("filters")]
        public IEnumerable<FilterOption>? Filters { get; set; }
        public override string ToString()
        {
            return base.ToString();
        }

        /// <summary>
        /// get filter expressions logic
        /// </summary>
        /// <param name="logicType"></param>
        /// <returns></returns>
        public string GetFilterLogic() => Logic switch
        {
            LogicType.And => " && ",
            LogicType.Or => " || ",
            _ => throw new ArgumentException($"{Logic} is not support"),
        };
    }

    /// <summary>
    /// 嵌套的查询过滤选项, 代表字段内的字段和值的关系
    /// 典型样式为: 
    /// Name eq '张三'
    /// Age gt 20
    /// Name co '张三'
    /// not support: contains(Name, '张三')
    /// not support: contains(tolower(Name), 'lucy')
    /// not support: Name not eq '张三'
    /// not support: Name eq '张三' and Age ge 20
    /// not support: Age ge 20 and (Name co '张' or Name co '李')
    /// not support: Age ge 20 and (Name co '张' or Name co '李' and Gender eq 'Male')
    /// not support: Age ge 20 and (Name co '张' or Name co '李') or Gender eq 'Male'
    /// not support: Age ge 20 and (Name co '张' or Name co '李' and Gender eq 'Male') or UserType eq 'Administrator'
    /// </summary>
    public class NestedFilterOption<T> : FilterOption<T>
    {
        /// <summary>
        /// logic expression list
        /// </summary>
        internal static readonly string[] LogicExpression = new string[] { " and ", " or " };

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public NestedFilterOption()
        {
        }
        /// <summary>
        /// 字符串 filter 表示形式参数的构造函数
        /// </summary>
        /// <param name="filter"></param>
        public NestedFilterOption(string filter)
        {
            //目前仅支持一级嵌套, 且不支持小括号表达式
            var values = filter.Split(LogicExpression, StringSplitOptions.RemoveEmptyEntries);
            if (values.IsNullOrEmpty())
            {
                throw new ArgumentException($"filter {filter} expression error!");
            }

            var filters = new List<FilterOption<T>>();
            foreach (var value in values)
            {
                filters.Add(new FilterOption<T>(value));
            }

            Filters = filters;
        }

        /// <summary>
        /// 内部字段之间的逻辑, and, or等
        /// </summary>
        [JsonPropertyName("logic")]
        public LogicType? Logic { get; set; }
        /// <summary>
        /// 内部字段选项
        /// </summary>
        [JsonPropertyName("filters")]
        public IEnumerable<FilterOption<T>>? Filters { get; set; }

        public override string ToString()
        {
            return base.ToString();
        }

        /// <summary>
        /// get filter expressions logic
        /// </summary>
        /// <param name="logicType"></param>
        /// <returns></returns>
        public string GetFilterLogic() => Logic switch
        {
            LogicType.And => " && ",
            LogicType.Or => " || ",
            _ => throw new ArgumentException($"{Logic} is not support"),
        };
    }
}
